#include <iostream>
#include <gtkmm.h>
 
class Worker {
  public:
 
    Worker() : thread(0), stop(false) {}
 
    // Called to start the processing on the thread
    void start () {
      thread = Glib::Thread::create(sigc::mem_fun(*this, &Worker::run), true);
    }
 
    // When shutting down, we need to stop the thread
    ~Worker() {
      {
        Glib::Mutex::Lock lock (mutex);
        stop = true;
      }
      if (thread)
        thread->join(); // Here we block to truly wait for the thread to complete
    }
 
    Glib::Dispatcher sig_done;
 
  protected:
    // This is where the real work happens
    void run () {
 
      while(true) {
        {
          Glib::Mutex::Lock lock (mutex);
          if (stop) break;
        }
        sleep(5);
        std::cout << "Thread write!" << std::endl;
        sig_done();
        break;
      }
    }
 
    Glib::Thread * thread;
    Glib::Mutex mutex;
    bool stop;
};
 
class MyWindow : public Gtk::Window {
 
  public:
    MyWindow () : thrashHive("Go!") {
      bee = NULL;
      thrashHive.signal_clicked().connect(sigc::mem_fun(*this, &MyWindow::go));
      add(thrashHive);
      show_all();
    }
 
    void go () {
      if(bee != NULL)
        return;
 
      bee = new Worker();
      bee->sig_done.connect(sigc::mem_fun(*this, &MyWindow::beeDone));
      bee->start();
 
      thrashHive.set_sensitive(false);
      thrashHive.set_label("Working");
    }
 
    void beeDone () {
      delete bee;
      bee = NULL;
      thrashHive.set_sensitive(true);
      thrashHive.set_label("Go!");
    }
 
  private:
    Gtk::Button thrashHive;
    Worker * bee;
 
};
 
int main (int argc , char ** argv) {
 
  if(!Glib::thread_supported()) Glib::thread_init();
 
  Gtk::Main kit (argc, argv);
  MyWindow win;
  Gtk::Main::run (win);
  return 0;
}
